package org.budo.graph.service.util;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.budo.ehcache.config.annotation.entity.EhCacheConfigEntity;
import org.budo.ehcache.config.annotation.factory.BudoEhcacheAnnotationConfigFactoryBean;
import org.budo.graph.Constant;
import org.budo.graph.entity.EhcacheStatistics;
import org.budo.support.freemarker.FreemarkerUtil;
import org.budo.support.lang.util.MapUtil;
import org.budo.support.lang.util.ReflectUtil;
import org.budo.support.lang.util.StringUtil;
import org.budo.support.slf4j.Slf4j;
import org.budo.support.spring.context.aware.BudoApplicationContextAware;
import org.budo.support.spring.io.util.ResourceUtil;
import org.budo.support.spring.util.SpringUtil;
import org.slf4j.Logger;
import org.springframework.context.ApplicationContext;

import com.alibaba.druid.stat.DruidStatService;

import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager;

/**
 * @author lmw
 */
public class EhcacheStatisticsUtil {
    private static final Logger log = Slf4j.getLogger();

    private static final boolean HAS_EHCACHE = ReflectUtil.hasClass("net.sf.ehcache.Cache");

    private static Map<String, EhCacheConfigEntity> _cacheConfigMap;

    public static List<EhcacheStatistics> listEhcacheStatistics(CacheManager cacheManager) {
        String[] cacheNames = cacheManager.getCacheNames();
        if (null == cacheNames || cacheNames.length < 1) {
            return new ArrayList<EhcacheStatistics>();
        }

        List<EhcacheStatistics> list = new ArrayList<EhcacheStatistics>();
        for (String cacheName : cacheNames) {
            Cache cache = cacheManager.getCache(cacheName);
            list.add(new EhcacheStatistics(cache));
        }
        return list;
    }

    public static EhCacheConfigEntity getEhCacheConfigEntity(String cacheName) {
        Map<String, EhCacheConfigEntity> conf = getEhCacheConfigEntityMap();
        return null == conf ? null : conf.get(cacheName);
    }

    public static Map<String, EhCacheConfigEntity> getEhCacheConfigEntityMap() {
        if (null != _cacheConfigMap) {
            return _cacheConfigMap;
        }

        BudoApplicationContextAware applicationContextAware = BudoApplicationContextAware.getInstance();
        if (null == applicationContextAware) {
            log.warn("#51 BudoApplicationContextAware is null");
            return null;
        }

        ApplicationContext applicationContext = applicationContextAware.getApplicationContext();
        if (null == applicationContext) {
            log.warn("#57 applicationContext is null, applicationContextAware=" + applicationContextAware);
            return null;
        }

        BudoEhcacheAnnotationConfigFactoryBean configBean = SpringUtil.getBean(applicationContext, BudoEhcacheAnnotationConfigFactoryBean.class);
        if (null == configBean) {
            log.warn("#63 BudoEhcacheAnnotationConfigFactoryBean not found, applicationContext=" + applicationContext);
            return null;
        }

        _cacheConfigMap = configBean.getCacheConfigMap();
        if (null == _cacheConfigMap) {
            log.warn("#69 getEhCacheConfigEntity not found, configBean=" + configBean);
            return null;
        }

        return _cacheConfigMap;
    }

    public static String writeEhcacheStatisticsResponse(ApplicationContext applicationContext, String url) {
        try {
            if (!HAS_EHCACHE) {
                return "NO_EHCACHE";
            }

            CacheManager cacheManager = SpringUtil.getBean(applicationContext, CacheManager.class);
            if (null == cacheManager) {
                return "eh.CacheManager in applicationContext is null";
            }

            if (StringUtil.startsWith(url, "/ehcache-statistics-clear-")) {
                String name = url.replace("/ehcache-statistics-clear-", "");
                Cache cache = cacheManager.getCache(name);
                if (null == cache) {
                    log.error("writeEhcacheStatisticsResponse, Cache[" + name + "] is null, url=" + url);
                    return "Cache[" + name + "] is null";
                }

                log.warn("writeEhcacheStatisticsResponse, Cache[" + name + "] cleared, url=" + url);
                cache.removeAll();
                return "Cache[" + name + "] cleared";
            } else {
                String inputString = ResourceUtil.classPathResourceInputStreamToString(Constant.GRAPH_TEMPLATE_PATH + "/ehcache-statistics.htm");
                List<EhcacheStatistics> cacheStatList = listEhcacheStatistics(cacheManager);

                Map<String, Object> data = MapUtil.stringObjectMap("cacheStatList", cacheStatList, //
                        "RequestParameters", DruidStatService.getParameters(url));

                return FreemarkerUtil.freemarkerRender(inputString, data);
            }
        } catch (Throwable e) {
            log.error("#114 writeEhcacheStatisticsResponse error, e=" + e, e);
            return "ehcache_statistics_error_" + e;
        }
    }
}
